package org.jeecg.modules.car.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.ForeignResult;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.RedisKeyConstant;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.MD5Utils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.StringUtils;
import org.jeecg.entity.car.*;
import org.jeecg.enums.PayModeEnum;
import org.jeecg.enums.car.CarEntryTypeEnum;
import org.jeecg.enums.car.CarIsExitEnum;
import org.jeecg.enums.car.CarOrderTypeEnum;
import org.jeecg.enums.car.CarSyncStatusEnum;
import org.jeecg.enums.common.PayTypeEnum;
import org.jeecg.lock.client.RedissonLockClient;
import org.jeecg.modules.car.entity.CarParkInfo;
import org.jeecg.modules.car.mapper.CarOrderMapper;
import org.jeecg.modules.car.service.*;
import org.jeecg.modules.system.util.RestTemplateUtil;
import org.jeecg.vo.car.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 *  外部系统-对接王舟车禁系统
 */
@Slf4j
@Service
public class ForeignCarJGSService {
    @Autowired
    private RestTemplateUtil restTemplateUtil;
    @Autowired
    private ICarParkInfoService carParkInfoService;
    @Autowired
    private ICarInfoService carInfoService;
    @Autowired
    private ICarParkingRecordService carParkingRecordService;
    @Autowired
    private ICarOfflinePayRecordService carOfflinePayRecordService;
    @Autowired
    private ForeignCarShParkingService foreignCarShParkingService;
    @Autowired
    private CarOrderMapper carOrderMapper;
    @Autowired
    private RedissonLockClient lockClient;
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private ICarPortService carPortService;

    @Value("${foreign-os.url}")
    private String outOsUrl;

    private static final String appKey = "pttest1234567";

    /**
     * 获取车场车类信息
     * @param parkId
     * @return
     */
    public Result<List<ForeignCarTypeResp>> getParkCarType(String parkId){
        Map<String,Object> paramMap = new LinkedHashMap<>();
        String url = outOsUrl + "getParkCarType";
        paramMap.put("park_id",parkId);
        paramMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());
        String sign = createSign(paramMap);
        if (sign != null){
            sign = MD5Utils.getMd5(sign).toUpperCase();
            paramMap.put("sign",sign);
        }
        JSONObject jsonObject =  restTemplateUtil.postForEntity(paramMap,url,null);
        String status = jsonObject.getString("status");
        if ("1".equals(status)){
            JSONArray jsonArray =  jsonObject.getJSONArray("data");
            List<ForeignCarTypeResp> typeRespList = jsonArray.toJavaList(ForeignCarTypeResp.class);
            return Result.ok(typeRespList);
        } else {
            return Result.error(jsonObject.getString("message"));
        }

    }

    /**
     * 获取车场车型信息
     * @param parkId
     * @return
     */
    public Result<List<ForeignCarModelResp>> getParkCarModel(String parkId){
        Map<String,Object> paramMap = new LinkedHashMap<>();
        String url = outOsUrl + "getParkCarModel";
        paramMap.put("park_id",parkId);
        paramMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());
        String sign = createSign(paramMap);
        if (sign != null){
            sign = MD5Utils.getMd5(sign).toUpperCase();
            paramMap.put("sign",sign);
        }
        JSONObject jsonObject =  restTemplateUtil.postForEntity(paramMap,url,null);
        String status = jsonObject.getString("status");
        if ("1".equals(status)){
           JSONArray jsonArray =  jsonObject.getJSONArray("data");
           List<ForeignCarModelResp> modelRespList = jsonArray.toJavaList(ForeignCarModelResp.class);
           return Result.ok(modelRespList);
        } else {
           return Result.error(jsonObject.getString("message"));
        }
    }

    /**
     * 删除月租车
     * @param carMonthlyRent
     * @return
     */
    public Result<String> delMonthlyRent(ForeignCarMonthlyRentReq carMonthlyRent){
        Map<String,Object> paramMap = new LinkedHashMap<>();
        String url = outOsUrl + "delMonthlyRent";
        paramMap.put("park_id", carMonthlyRent.getPark_id());
        paramMap.put("plate_number", carMonthlyRent.getPlate_number());
        paramMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());
        Map<String,Object> signMap = new LinkedHashMap<>();
        signMap.put("park_id", carMonthlyRent.getPark_id());
        signMap.put("plate_number", carMonthlyRent.getPlate_number());
        signMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());
        String signValue = createSign(signMap);
        if (signValue != null){
            String sign = MD5Utils.getMd5(signValue).toUpperCase();
            paramMap.put("sign",sign);
        }
        JSONObject jsonObject = restTemplateUtil.postForEntity(paramMap,url,null);
        log.info("车禁删除信息返回：{}", jsonObject);
        if (jsonObject != null){
            String status = jsonObject.getString("status");
            String message = jsonObject.getString("message");
            if ("1".equals(status)){
                return Result.ok(message);
            }
            return Result.error(message);
        }
        return Result.error(500,"响应为空");
    }

    /**
     * 更新车禁车辆信息公共入口
     * @param carInfo
     * @param startTime
     * @param endTime
     * @return
     */
    public Result<String> saveMonthlyRentUtils(CarInfo carInfo, String startTime, String endTime){
        try {
            ForeignCarMonthlyRentReq rentReq = new ForeignCarMonthlyRentReq();
            rentReq.setPark_id(carInfo.getOutParkId());
            if (StringUtils.isNotBlank(carInfo.getOwnerName())){
                rentReq.setEmp_name(carInfo.getOwnerName());
            } else {
                rentReq.setEmp_name(carInfo.getMobile());
            }
            rentReq.setEmp_moblie(carInfo.getMobile());
            rentReq.setPlate_number(carInfo.getCarNo());
            rentReq.setCartypeid(carInfo.getOutCarType());
            rentReq.setCarmodelid(carInfo.getOutCarModel());
            rentReq.setBegindate(startTime);
            rentReq.setEnddate(endTime);
            return this.saveMonthlyRent(rentReq);
        }catch (Exception e){
            log.error("车禁更新车辆信息异常",e);
            return Result.error(500,"更新车禁信息异常");
        }
    }

    /**
     * 添加修改月租车
     * @param carMonthlyRent
     * @return
     */
    public Result<String> saveMonthlyRent(ForeignCarMonthlyRentReq carMonthlyRent){
        try{
            Map<String,Object> paramMap = new LinkedHashMap<>();
            String url = outOsUrl + "saveMonthlyRent";
            paramMap.put("park_id",carMonthlyRent.getPark_id());
            paramMap.put("emp_name",carMonthlyRent.getEmp_name());
            paramMap.put("emp_moblie",carMonthlyRent.getEmp_moblie());
            paramMap.put("plate_number",carMonthlyRent.getPlate_number());
            if (StringUtils.isNotEmpty(carMonthlyRent.getFamily_address())){
                paramMap.put("family_address",carMonthlyRent.getFamily_address());
            }
            paramMap.put("cartypeid",carMonthlyRent.getCartypeid());
            paramMap.put("carmodelid",carMonthlyRent.getCarmodelid());
            paramMap.put("begindate",carMonthlyRent.getBegindate());
            paramMap.put("enddate",carMonthlyRent.getEnddate());
            paramMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());

            Map<String,Object> signMap = new LinkedHashMap<>();
            signMap.put("park_id",carMonthlyRent.getPark_id());
            signMap.put("emp_name",carMonthlyRent.getEmp_name());
            signMap.put("plate_number",carMonthlyRent.getPlate_number());
            signMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());
            String signValue = createSign(signMap);
            if (signValue != null){
                String sign = MD5Utils.getMd5(signValue).toUpperCase();
                paramMap.put("sign",sign);
            }
            JSONObject jsonObject = restTemplateUtil.postForEntity(paramMap,url,null);
            log.info("新增车禁信息返回：{}", jsonObject);
            if (jsonObject != null){
                String status = jsonObject.getString("status");
                String message = jsonObject.getString("message");
                if ("1".equals(status)){
                    return Result.ok(message);
                }
                return Result.error(message);
            }
        }catch (Exception e){
            log.error("向车禁同步月卡信息处理异常",e);
        }
        return Result.error(500,"响应为空");
    }


    /**
     *  获取临停缴费接口
     * @param recordId  入场记录id
     * @param parkId   车禁平台的车场id
     * @param carNo  车牌号
     * @return
     */
    public Result<ForeignCarTempCostResp> calculatingTempCost(String recordId,String parkId,String carNo){
        Map<String,Object> paramMap = new LinkedHashMap<>();
        String url = outOsUrl + "calculatingTempCost";
        paramMap.put("parking_id",parkId);
        paramMap.put("record_id",recordId);
        paramMap.put("plate_num",carNo);
        paramMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());
        String sign = createSign(paramMap);
        if (sign != null){
            sign = MD5Utils.getMd5(sign).toUpperCase();
            paramMap.put("sign",sign);
        }
        JSONObject jsonObject = restTemplateUtil.postForEntity(paramMap,url,null);
        String status = jsonObject.getString("status");
        if ("1".equals(status)){
            JSONObject jsonData =  jsonObject.getJSONObject("data");
            ForeignCarTempCostResp resp =  jsonData.toJavaObject(ForeignCarTempCostResp.class);
            resp.setRecord_id(recordId);
            try{
                BigDecimal payMoney = resp.getTotal_fee() == null? BigDecimal.ZERO:new BigDecimal(resp.getTotal_fee());
                carParkingRecordService.update(Wrappers.<CarParkingRecord>update().lambda().set(CarParkingRecord::getPayMoney,payMoney.intValue())
                        .eq(CarParkingRecord::getRecordId,recordId));
            }catch (Exception e){
                log.error("临停缴费接口,保存费用处理异常",e);
            }
            return Result.ok(resp);
        } else {
            return Result.error(jsonObject.getString("message"));
        }
    }

    /**
     * 无牌车扫码进出，以及有牌车通道口扫码缴费
     * @param parkId  车场id
     * @param gateId  通道id
     * @param openId  无牌车传微信OpenID,有牌车传车牌号
     * @return
     */
    public Result noPlateQRcode(String parkId,String gateId,String openId){
        Map<String,Object> paramMap = new LinkedHashMap<>();
        String url = outOsUrl + "noPlateQRcode";
        paramMap.put("park_id",parkId);
        paramMap.put("lane_no",gateId);
        paramMap.put("open_id",openId);
        paramMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());
        Map<String,Object> signMap = new LinkedHashMap<>();
        signMap.put("park_id",parkId);
        signMap.put("lane_no",gateId);
        signMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());
        String signValue = createSign(signMap);
        if (signValue != null){
            String sign = MD5Utils.getMd5(signValue).toUpperCase();
            paramMap.put("sign",sign);
        }
        JSONObject jsonObject = restTemplateUtil.postForEntity(paramMap,url,null);
        String status = jsonObject.getString("status");
        String message = jsonObject.getString("message");
        if ("1".equals(status)){
            JSONObject jsonData =  jsonObject.getJSONObject("data");
            if (jsonData == null){
                if ("扫码入场成功".equals(message)){
                    return Result.ok(message);
                } else {
                    return Result.error(message);
                }
            }
            ForeignCarTempCostResp resp =  jsonData.toJavaObject(ForeignCarTempCostResp.class);
            return Result.ok(resp);
        } else {
            return Result.error(message);
        }
    }

    /**
     * 临停支付通知接口
     * @param carPayTempReq
     * @return
     */
    public Result<String> payTempCost(ForeignCarIotPayTempReq carPayTempReq){
        Map<String,Object> paramMap = new LinkedHashMap<>();
        String url = outOsUrl + "payTempCost";
        paramMap.put("park_id",carPayTempReq.getPark_id());
        paramMap.put("plate_number",carPayTempReq.getPlate_number());
        paramMap.put("order_no",carPayTempReq.getOrder_no());
        paramMap.put("pay_fee",carPayTempReq.getPay_fee());
        paramMap.put("order_id",carPayTempReq.getOrder_id());
        paramMap.put("pay_type",carPayTempReq.getPay_type());
        paramMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());
        Map<String,Object> signMap = new LinkedHashMap<>();
        signMap.put("park_id",carPayTempReq.getPark_id());
        signMap.put("order_no",carPayTempReq.getOrder_no());
        signMap.put("plate_number",carPayTempReq.getPlate_number());
        signMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());
        String signValue = createSign(signMap);
        if (signValue != null){
            String sign = MD5Utils.getMd5(signValue).toUpperCase();
            paramMap.put("sign",sign);
        }
        JSONObject jsonObject = restTemplateUtil.postForEntity(paramMap,url,null);
        if (jsonObject != null){
            String status = jsonObject.getString("status");
            String message = jsonObject.getString("message");
            if ("1".equals(status)){
                return Result.ok(message);
            }
            return Result.error(message);
        }
        return Result.error(500,"响应为空");
    }



    /**
     * 根据车场id获取通道列表
     * @param parkId
     * @return
     */
    public Result<List<ForeignCarGateResp>> getParkGate(String parkId){
        Map<String,Object> paramMap = new LinkedHashMap<>();
        String url = outOsUrl + "getParkGate";
        paramMap.put("park_id",parkId);
        paramMap.put("appKey", MD5Utils.getMd5(appKey).toUpperCase());
        String signValue = createSign(paramMap);
        if (signValue != null){
            String sign = MD5Utils.getMd5(signValue).toUpperCase();
            paramMap.put("sign",sign);
        }
        JSONObject jsonObject = restTemplateUtil.postForEntity(paramMap,url,null);
        if (jsonObject != null){
            String status = jsonObject.getString("status");
            String message = jsonObject.getString("message");
            if ("1".equals(status)){
                JSONArray jsonArray =  jsonObject.getJSONArray("data");
                List<ForeignCarGateResp> gateRespList = jsonArray.toJavaList(ForeignCarGateResp.class);
                return Result.ok(gateRespList);
            }
            return Result.error(message);
        }
        return Result.error(500,"响应为空");
    }

    /**
     * 接收 车场未确定订单推送数据
     * @param record
     * @return
     */
    @Transactional
    public ForeignResult pushCarWithoutPayRecord(ForeignWithoutPayRecord record){
        try {
            CarParkingRecord parkingRecord =  carParkingRecordService.getByRecordId(record.getOnlyCode(),null);
            if (parkingRecord == null){
                log.warn("进出记录不存在,recordId:{}",record.getOnlyCode());
                return ForeignResult.error("进出记录不存在！");
            }
            CarInfo carInfo = carInfoService.getByCarNo(record.getCarNo(), parkingRecord.getParkId());
            String carId = "";
            if (carInfo != null){
                carId = carInfo.getId();
            }
            CarOrder carOrder = new CarOrder();
            carOrder.setId(String.valueOf(IdWorker.getId()));
            carOrder.setTenantId(parkingRecord.getTenantId());
            carOrder.setProjectId(parkingRecord.getProjectId());
            carOrder.setParkId(parkingRecord.getParkId());
            carOrder.setSn(record.getOnlyCode());
            carOrder.setCarId(carId);
            carOrder.setOrderNo(record.getParkOrder());
            carOrder.setCarNo(record.getCarNo());
            carOrder.setCreateTime(new Date());
            carOrder.setUpdateTime(new Date());
            carOrder.setOrderType(CarOrderTypeEnum.ORDER_TYPE_TEMP.getCode());
            carOrder.setPayMode(PayModeEnum.PAY_MODE_OFFLINE.getCode());
            carOrder.setPayType(PayTypeEnum.PAY_METHOD_XIANJIN.getCode().toString());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (StringUtils.isNotBlank(record.getNowTime())){
                carOrder.setPayTime(sdf.parse(record.getNowTime()));
            }
            carOrder.setChargeType(2);
            carOrder.setCarTypeName(record.getCarType());
            carOrder.setRemarks(record.getReason());
            carOrder.setPayDue(new BigDecimal(record.getAmount()));
            carOrder.setPayReduced(new BigDecimal(0));
            carOrder.setPayAmount(new BigDecimal(0));
            carOrderMapper.addOrUpdate(carOrder);
        }catch (Exception e){
            log.error("车场未确定订单推送数据异常",e);
            return ForeignResult.error("车场未确定订单推送数据异常");
        }
        return ForeignResult.ok();
    }


    /**
     * 接收 车场线下缴费记录推送
     * @param record
     * @return
     */
    @Transactional
    public ForeignResult pushCarOfflinePayRecord(ForeignCarOfflinePayRecord record){
        try {
            //判断车场是否存在
//            CarParkInfo carParkInfo = carParkInfoService.getByOutParkId(record.getPark_id());
//            if (carParkInfo == null){
//                log.warn("车场不存在,parkId:{}",record.getPark_id());
//                return ForeignResult.error("车场不存在！");
//            }
           CarParkingRecord parkingRecord =  carParkingRecordService.getByRecordId(record.getOnlyCode(),null);
           if (parkingRecord == null){
                log.warn("进出记录不存在,recordId:{}",record.getOnlyCode());
                return ForeignResult.error("进出记录不存在！");
            }
            CarInfo carInfo = carInfoService.getByCarNo(record.getCarNo(), parkingRecord.getParkId());
            String carId = "";
            if (carInfo != null){
                carId = carInfo.getId();
            }
            CarOfflinePayRecord carOfflinePayRecord = new CarOfflinePayRecord();
            carOfflinePayRecord.setEntrancegateId(record.getInLaneCode());
            carOfflinePayRecord.setExitgateId(record.getInLaneCode());
//            carOfflinePayRecord.setReleaseType(record.getRelease_type());
            carOfflinePayRecord.setTenantId(parkingRecord.getTenantId());
            carOfflinePayRecord.setProjectId(parkingRecord.getProjectId());
            carOfflinePayRecord.setParkId(parkingRecord.getParkId());
            carOfflinePayRecord.setOutParkId(parkingRecord.getOutParkId());
            carOfflinePayRecord.setPayMode(PayModeEnum.PAY_MODE_OFFLINE.getCode());
            carOfflinePayRecord.setPayType(record.getPayType());
            carOfflinePayRecord.setParkName(parkingRecord.getParkName());
            carOfflinePayRecord.setCarId(carId);
//            carOfflinePayRecord.setCarType(record.getCar_type());
//            carOfflinePayRecord.setCarSize(record.getCar_size());
            carOfflinePayRecord.setCarNo(record.getCarNo());
            carOfflinePayRecord.setRecordId(record.getOnlyCode());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (StringUtils.isNotBlank(record.getInTime())){
                carOfflinePayRecord.setEntranceTime(sdf.parse(record.getInTime().replace("/","-")));
            }
            if (StringUtils.isNotBlank(record.getCreateTime())){
                carOfflinePayRecord.setExitTime(sdf.parse(record.getCreateTime()));
            }
            if (StringUtils.isNotBlank(record.getAmount())){
                carOfflinePayRecord.setAmount(new BigDecimal(record.getAmount()));
            }
            if (StringUtils.isNotBlank(record.getAmountTotle())){
                carOfflinePayRecord.setDue(new BigDecimal(record.getAmountTotle()));
            }
            if (StringUtils.isNotBlank(record.getDiscountAmount())){
                carOfflinePayRecord.setReduceAmount(new BigDecimal(record.getDiscountAmount()));
            }
            carOfflinePayRecord.setCreateTime(new Date());
            carOfflinePayRecord.setUpdateTime(new Date());
            carOfflinePayRecord.setId(String.valueOf(IdWorker.getId()));
            carOfflinePayRecordService.addOrUpdate(carOfflinePayRecord);
            //添加订单信息
            CarOrder carOrder = new CarOrder();
            carOrder.setId(String.valueOf(IdWorker.getId()));
            carOrder.setTenantId(carOfflinePayRecord.getTenantId());
            carOrder.setProjectId(carOfflinePayRecord.getProjectId());
            carOrder.setParkId(carOfflinePayRecord.getParkId());
            carOrder.setSn(carOfflinePayRecord.getRecordId());
            carOrder.setCarId(carId);
            carOrder.setCarNo(carOfflinePayRecord.getCarNo());
            carOrder.setCreateTime(new Date());
            carOrder.setUpdateTime(new Date());
            carOrder.setOrderType(CarOrderTypeEnum.ORDER_TYPE_TEMP.getCode());
            carOrder.setPayMode(PayModeEnum.PAY_MODE_OFFLINE.getCode());
            carOrder.setPayType(PayTypeEnum.PAY_METHOD_XIANJIN.getCode().toString());
            carOrder.setCarTypeName("临停车");
            carOrder.setChargeType(0);
            carOrder.setPayTime(carOfflinePayRecord.getExitTime());
            carOrder.setPayDue(carOfflinePayRecord.getDue());
            carOrder.setPayReduced(carOfflinePayRecord.getReduceAmount());
            carOrder.setPayAmount(carOfflinePayRecord.getAmount());
            carOrder.setRemarks("车场推送订单");
            carOrderMapper.addOrUpdate(carOrder);
        } catch (ParseException e) {
            log.error("车场线下缴费记录推送异常",e);
            return ForeignResult.error("车场线下缴费记录推送异常");
        }
        return ForeignResult.ok();
    }

    /**
     * 接收- 车场车辆进出记录推送
     * @param record
     * @return
     */
//    @Transactional
    public ForeignResult pushParkingRecord(ForeignCarParkingRecord record) {
        //判断车场是否存在
        CarParkInfo carParkInfo = carParkInfoService.getByOutParkId(record.getPark_id());
        if (carParkInfo == null){
            return ForeignResult.error("车场不存在！");
        }
        // todo tenantId
        CarInfo carInfo = carInfoService.getByCarNo(record.getPlate_number(),carParkInfo.getId());
        String carId = "";
        if (carInfo != null){
            carId = carInfo.getId();
        }
        CarParkingRecord carParkingRecord = new CarParkingRecord();
        carParkingRecord.setId(String.valueOf(IdWorker.getId()));
        carParkingRecord.setTenantId(carParkInfo.getTenantId());
        carParkingRecord.setProjectId(carParkInfo.getProjectId());
        carParkingRecord.setParkId(carParkInfo.getId());
        carParkingRecord.setOutParkId(record.getPark_id());
        carParkingRecord.setParkName(record.getPark_name());
        carParkingRecord.setCarId(carId);
        carParkingRecord.setCarNo(record.getPlate_number());
        carParkingRecord.setRecordId(record.getRecord_id());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            carParkingRecord.setEntranceTime(sdf.parse(record.getEntrance_time()));
            if(StringUtils.isNotEmpty(record.getExit_time())){
                carParkingRecord.setExitTime(sdf.parse(record.getExit_time()));
            }
        } catch (ParseException e) {
           log.error("车场进出记录处理异常",e);
        }
        carParkingRecord.setEntrancegateId(record.getEntrancegate_id());
        carParkingRecord.setExitgateId(record.getExitgate_id());
        carParkingRecord.setReleaseType(record.getRelease_type());
        carParkingRecord.setCarType(record.getCartype_id());
        carParkingRecord.setCarModel(record.getCarmodel_id());
        carParkingRecord.setEnterType(record.getEnter_type());
        carParkingRecord.setPlateColor(record.getPlate_color());
//        carParkingRecord.setInimgPicture(record.getInimg_picture());
//        carParkingRecord.setOutimgPicture(record.getOutimg_picture());
        carParkingRecord.setIsExit(record.getIs_exit());
        carParkingRecord.setCreateTime(new Date());
        carParkingRecord.setUpdateTime(new Date());
        carParkingRecord.setId(String.valueOf(IdWorker.getId()));
        Integer count = carParkingRecordService.addOrUpdate(carParkingRecord);
        String key = RedisKeyConstant.CAR_RECORD_KEY + carParkingRecord.getRecordId() + "_" + carParkingRecord.getIsExit();
        boolean getLock = lockClient.tryLock(key,0,60);
        if (!getLock){
            return ForeignResult.ok("结果:" + count);
        }
        try {
            if (CarIsExitEnum.CAR_IS_EXIT_IN.getCode().equals(record.getIs_exit())){
                parkingIn(record, carInfo); //入场
            }else {//出场
                parkingOut(record, carInfo);
            }
            //更新车辆表在场状态
            if (carInfo != null){
                carInfoService.updateIsExist(carInfo.getId(),carInfo.getTenantId(),record.getIs_exit());
            }
        } catch (Exception e) {
            log.error("AB车进出记录处理异常",e);
        }
        //上传数据到公共平台  -- 后续优化到MQ TODO
        try{
            if (StringUtils.isBlank(carParkInfo.getSuperviseParkingId())){
                log.warn("车场:{}未配置监管平台基础信息,上传失败!",carParkInfo.getParkName());
                return ForeignResult.ok("结果:" + count);
            }
            ForeignCarShLeaveReq leaveReq = new ForeignCarShLeaveReq();
            leaveReq.setParkingId(carParkInfo.getSuperviseParkingId());
            leaveReq.setAppId(carParkInfo.getSuperviseAppId());
            leaveReq.setPassword(carParkInfo.getSupervisePassword());
            if (carParkingRecord.getEnterType() != 0){
                leaveReq.setParkType(1); //1:临停
            } else if (StringUtils.isBlank(carId)){
                leaveReq.setParkType(1); //1:临停
            } else {
                leaveReq.setParkType(2); //2:月卡
            }
            leaveReq.setPlateId(carParkingRecord.getCarNo());
            leaveReq.setLaneType(1);
            leaveReq.setVehicleType(1);
            String counterFreeKey = RedisKeyConstant.CAR_COUNTER_FREE + carParkInfo.getId(); //空闲车位
            if (!redisUtil.hasKey(counterFreeKey)){
                redisUtil.set(counterFreeKey,1000);
            }
            String counterEnterKey = RedisKeyConstant.CAR_COUNTER_ARRIVE  + carParkInfo.getId(); //进场数
            String counterLeaveKey = RedisKeyConstant.CAR_COUNTER_LEAVE  + carParkInfo.getId(); //离场数
            if (carParkingRecord.getIsExit() == 1){ // 入场
                leaveReq.setFreeBerth((int)redisUtil.decr(counterFreeKey,1));
                redisUtil.calDaySeq(counterEnterKey);
                boolean res = foreignCarShParkingService.arrive(leaveReq);
                if (res){
                    carParkingRecordService.update(Wrappers.<CarParkingRecord>update().lambda().set(CarParkingRecord::getArrivedStatus, true)
                            .eq(CarParkingRecord::getId, carParkingRecord.getId()).eq(CarParkingRecord::getTenantId,carParkingRecord.getTenantId()));//更新上传状态
                }
            } else { //出场
                leaveReq.setFreeBerth((int)redisUtil.incr(counterFreeKey,1));
                redisUtil.calDaySeq(counterLeaveKey);
                leaveReq.setPayType("unknown"); //其他
                Calendar carEnter = Calendar.getInstance();
                carEnter.setTime(carParkingRecord.getEntranceTime());
                Calendar carLeave = Calendar.getInstance();
                carLeave.setTime(carParkingRecord.getExitTime());
                leaveReq.setParkingTime((int)(carLeave.getTimeInMillis() - carEnter.getTimeInMillis())/1000);
                CarParkingRecord outRecord = carParkingRecordService.getOne(Wrappers.<CarParkingRecord>query().lambda().eq(CarParkingRecord::getRecordId,carParkingRecord.getRecordId())
                        .eq(CarParkingRecord::getTenantId,carParkInfo.getTenantId()));
                leaveReq.setPayMoney(0);
                if (outRecord != null){
                    leaveReq.setPayMoney(outRecord.getPayMoney() * 100);
                }
                boolean res = foreignCarShParkingService.leave(leaveReq);
                if (res){
                    carParkingRecordService.update(Wrappers.<CarParkingRecord>update().lambda().set(CarParkingRecord::getLeaveStatus,true)
                            .eq(CarParkingRecord::getRecordId,carParkingRecord.getRecordId()).eq(CarParkingRecord::getTenantId,carParkingRecord.getTenantId()));   //更新上传状态
                }
            }
        }catch (Exception e){
            log.error("上传数据到公共平台处理异常:{}",e); //可打印异常栈信息
        }
        return ForeignResult.ok("结果:" + count);
    }

    //车辆进场处理逻辑
    private void parkingIn(ForeignCarParkingRecord record, CarInfo carInfo){
        //非固定车位车辆 && 不为正常入场车辆 （过期转临停，车位占用转临停 不做处理）
        if (carInfo == null || StringUtils.isBlank(carInfo.getCarPortId()) || !record.getEnter_type().equals(CarEntryTypeEnum.CAR_ENTRY_TYPE_0.getCode())){
            return;
        }
        CarPort carPort = carPortService.queryById(carInfo.getCarPortId(), carInfo.getTenantId());
        if(carPort.getIsAb() == 0){
            return;
        }
        List<CarInfo> carInfoList = carInfoService.getByCarPortId(carInfo.getCarPortId());
        //车位只有一辆车不做处理
        if(carInfoList != null && carInfoList.size() == 1){
            return;
        }
        log.info("AB----------《 车辆进场推送处理record：{}，carInfo：{}", record, carInfo);
        List<String> carNos = carInfoList.stream().map(CarInfo::getCarNo).collect(Collectors.toList());
        log.info("进场---车位下所有车辆信息：{}", carNos);
        //获取车场中已经进入的车辆信息
        carNos.removeAll(Arrays.asList(carInfo.getCarNo()));
        List<CarParkingRecord> parkingRecordList = carParkingRecordService.getByCarNosAndParkId(carInfo.getTenantId(), carNos, carInfo.getParkId());
        List<String> carNoIds = carInfoList.stream().map(CarInfo::getId).collect(Collectors.toList());//同一车位下车辆id
        List<String> recordCarNoIds = parkingRecordList.stream().map(CarParkingRecord::getCarId).collect(Collectors.toList());//已经在场的车辆id
        carNoIds.removeAll(recordCarNoIds);
        // 月卡车入场处理
        if (!carInfo.getLocalStartTime().equals(carInfo.getLocalEndTime())){
            //获取所有  不在车场内车辆
            log.info("月卡车入场，车场中已经存在的车辆：{}",parkingRecordList.stream().map(CarParkingRecord::getCarNo).collect(Collectors.toList()));
            List<CarInfo> carMonthlyRent = carInfoService.findByIds(carNoIds);
            for (CarInfo info : carMonthlyRent) {
                //车辆未审核通过 || 未同步车场 不做处理
                if (!(IParkConstants.CHECK_STATUS_PASSED == info.getCheckStatus()) || info.getSyncStatus().equals(CarSyncStatusEnum.SYNC_STATUS_NO.getCode())) {
                    continue;
                }
                //排除当前进场车辆
                if (info.getCarNo().equals(record.getPlate_number())){continue;}
                log.info("月卡车入场，修改未入场车辆为临停：{},开始、结束时间：{}", info.getCarNo(),record.getEntrance_time());
                ForeignCarMonthlyRentReq rentReq = new ForeignCarMonthlyRentReq();
                rentReq.setPark_id(info.getOutParkId());
                if (StringUtils.isNotBlank(info.getOwnerName())){
                    rentReq.setEmp_name(info.getOwnerName());
                } else {
                    rentReq.setEmp_name(info.getMobile());
                }
                rentReq.setEmp_moblie(info.getMobile());
                rentReq.setPlate_number(info.getCarNo());
                rentReq.setCartypeid(info.getOutCarType());
                rentReq.setCarmodelid(info.getOutCarModel());
                //将其他车辆开始到期时间设置为 月卡车进场时间
                rentReq.setBegindate(record.getEntrance_time());
                rentReq.setEnddate(record.getEntrance_time());
                Result<String> syncRes = saveMonthlyRent(rentReq);
                if (syncRes.isSuccess()){
                    info.setLocalStartTime(DateUtils.str2Date(record.getEntrance_time(), DateUtils.datetimeFormat));
                    info.setLocalEndTime(DateUtils.str2Date(record.getEntrance_time(), DateUtils.datetimeFormat));
                    carInfoService.updateFeeDate(info);
                    log.info("AB车车位占用转临停同步车场成功：{}", info.getCarNo());
                }else {
                    log.error("AB车车位占用转临停同步车场失败：{}", info.getCarNo());
                }
            }
        }
    }

    //车辆出场处理逻辑
    private void parkingOut(ForeignCarParkingRecord record, CarInfo carInfo){
        //非固定车位车辆 不做处理
        if (carInfo == null || StringUtils.isBlank(carInfo.getCarPortId())){
            return;
        }
        //车位信息
        CarPort carPort = carPortService.queryById(carInfo.getCarPortId(), carInfo.getTenantId());
        if (carPort.getIsAb() == 0){
            return;
        }
        List<CarInfo> carInfoList = carInfoService.getByCarPortId(carInfo.getCarPortId());
        //车位只有一辆车
        if(carInfoList != null && carInfoList.size() == 1){
            //&& 为临停
            if (carInfoList.get(0).getLocalStartTime() == carInfoList.get(0).getLocalEndTime()){
                log.info("车位只有一辆车且为临停车处理为月卡车：{}",carInfoList.get(0));
                List<CarInfo> carMonthlyRent = carInfoService.findByIds(Arrays.asList(carInfoList.get(0).getId()));
                ForeignCarMonthlyRentReq rentReq = new ForeignCarMonthlyRentReq();
                rentReq.setPark_id(carMonthlyRent.get(0).getOutParkId());
                if (StringUtils.isNotBlank(carMonthlyRent.get(0).getOwnerName())){
                    rentReq.setEmp_name(carMonthlyRent.get(0).getOwnerName());
                } else {
                    rentReq.setEmp_name(carMonthlyRent.get(0).getMobile());
                }
                rentReq.setEmp_moblie(carMonthlyRent.get(0).getMobile());
                rentReq.setPlate_number(carMonthlyRent.get(0).getCarNo());
                rentReq.setCartypeid(carMonthlyRent.get(0).getOutCarType());
                rentReq.setCarmodelid(carMonthlyRent.get(0).getOutCarModel());
                rentReq.setBegindate(DateUtils.date2Str(carPort.getLocalStartTime(),DateUtils.datetimeFormat));
                rentReq.setEnddate(DateUtils.date2Str(carPort.getLocalEndTime(),DateUtils.datetimeFormat));
                Result<String> syncRes = saveMonthlyRent(rentReq);
                if (syncRes.isSuccess()){
                    log.info("车位中只有一辆临停转月卡车成功：{}", carMonthlyRent.get(0).getCarNo());
                    carMonthlyRent.get(0).setLocalStartTime(carPort.getLocalStartTime());
                    carMonthlyRent.get(0).setLocalEndTime(carPort.getLocalEndTime());
                    carInfoService.updateFeeDate(carMonthlyRent.get(0));
                }else{
                    log.info("车位中只有一辆临停转月卡车失败：{}", carMonthlyRent.get(0).getCarNo());
                }
                return;
            }else {
                return;
            }
        }
        log.info("AB----------》车车辆出场推送处理record：{}，carInfo：{}", record, carInfo);
        List<String> carNos = carInfoList.stream().map(CarInfo::getCarNo).collect(Collectors.toList());
        log.info("出场---车位下所有车辆信息：{}", carNos);
        //获取车场中已经进入的车辆信息
        List<CarParkingRecord> parkingRecordList = carParkingRecordService.getByCarNosAndParkId(carInfo.getTenantId(), carNos,carInfo.getParkId());
        List<String> carNoIds = carInfoList.stream().map(CarInfo::getId).collect(Collectors.toList());//同一车位下车辆id
        List<String> recordCarNoIds = parkingRecordList.stream().map(CarParkingRecord::getCarId).collect(Collectors.toList());//已经在场的车辆id
        //出场时车场中已有其他车辆
        if (parkingRecordList != null && parkingRecordList.size() > 0){
            //月卡车出场
            if (!carInfo.getLocalStartTime().equals(carInfo.getLocalEndTime())){
                  //查询车场中已经存在的车辆是否为月卡车
                 List<CarInfo> monthCarNos = carInfoService.getMonthCarNo(carInfo.getParkId(),carInfo.getTenantId(), recordCarNoIds);
                 if (monthCarNos != null && monthCarNos.size() > 0){
                     log.info("月卡车出场，已入场车辆存在月卡车：{}", monthCarNos.stream().map(CarInfo::getCarNo).collect(Collectors.toList()));
                     carNoIds.removeAll(recordCarNoIds);//剔除车场中已经存在的车辆
                     List<CarInfo> carMonthlyRent = carInfoService.findByIds(carNoIds);
                     for (CarInfo info : carMonthlyRent) {
                         log.info("月卡车出场，修改未入场车辆为临停：{},开始、结束时间：{}", info.getCarNo(),record.getExit_time());
                         //车辆未审核通过 || 未同步车场 不做处理
                         if (!(IParkConstants.CHECK_STATUS_PASSED == info.getCheckStatus()) || info.getSyncStatus().equals(CarSyncStatusEnum.SYNC_STATUS_NO.getCode())) {
                             continue;
                         }
                         ForeignCarMonthlyRentReq rentReq = new ForeignCarMonthlyRentReq();
                         rentReq.setPark_id(info.getOutParkId());
                         if (StringUtils.isNotBlank(info.getOwnerName())){
                             rentReq.setEmp_name(info.getOwnerName());
                         } else {
                             rentReq.setEmp_name(info.getMobile());
                         }
                         rentReq.setEmp_moblie(info.getMobile());
                         rentReq.setPlate_number(info.getCarNo());
                         rentReq.setCartypeid(info.getOutCarType());
                         rentReq.setCarmodelid(info.getOutCarModel());
                         //将其他车辆开始到期时间设置为 月卡车出场时间
                         rentReq.setBegindate(record.getExit_time());
                         rentReq.setEnddate(record.getExit_time());
                         Result<String> syncRes = saveMonthlyRent(rentReq);
                         if (syncRes.isSuccess()){
                             info.setLocalStartTime(DateUtils.str2Date(record.getExit_time(), DateUtils.datetimeFormat));
                             info.setLocalEndTime(DateUtils.str2Date(record.getExit_time(), DateUtils.datetimeFormat));
                             carInfoService.updateFeeDate(info);
                             log.info("AB车车位占用转临停同步车场成功：{}", info.getCarNo());
                         }else {
                             log.error("AB车车位占用转临停同步车场失败：{}", info.getCarNo());
                         }
                     }
                 }else {//车场中无月卡车
                     carNoIds.removeAll(recordCarNoIds);//剔除车场中已经存在的车辆
                     List<CarInfo> carMonthlyRent = carInfoService.findByIds(carNoIds);
                     for (CarInfo info : carMonthlyRent) {
                         //车辆未审核通过 || 未同步车场 不做处理
                         if (!(IParkConstants.CHECK_STATUS_PASSED == info.getCheckStatus()) || info.getSyncStatus().equals(CarSyncStatusEnum.SYNC_STATUS_NO.getCode())) {
                             continue;
                         }
                         //去除当前已经是月卡车车辆
                         if (info.getCarNo().equals(carInfo.getCarNo())){continue;};
                         log.info("月卡车出场，车场中无月卡车 ，修改未在场的车辆为月卡：{},开始:{},结束时间：{}", info.getCarNo(),DateUtils.date2Str(carPort.getLocalStartTime(),DateUtils.datetimeFormat),DateUtils.date2Str(carPort.getLocalEndTime(),DateUtils.datetimeFormat));
                         ForeignCarMonthlyRentReq rentReq = new ForeignCarMonthlyRentReq();
                         rentReq.setPark_id(info.getOutParkId());
                         if (StringUtils.isNotBlank(info.getOwnerName())){
                             rentReq.setEmp_name(info.getOwnerName());
                         } else {
                             rentReq.setEmp_name(info.getMobile());
                         }
                         rentReq.setEmp_moblie(info.getMobile());
                         rentReq.setPlate_number(info.getCarNo());
                         rentReq.setCartypeid(info.getOutCarType());
                         rentReq.setCarmodelid(info.getOutCarModel());
                         rentReq.setBegindate(DateUtils.date2Str(carPort.getLocalStartTime(),DateUtils.datetimeFormat));
                         rentReq.setEnddate(DateUtils.date2Str(carPort.getLocalEndTime(),DateUtils.datetimeFormat));
                         Result<String> syncRes = saveMonthlyRent(rentReq);
                         if (syncRes.isSuccess()){
                             info.setLocalStartTime(carPort.getLocalStartTime());
                             info.setLocalEndTime(carPort.getLocalEndTime());
                             carInfoService.updateFeeDate(info);
                             log.info("AB车临停转车位时间同步车场成功：{}", info.getCarNo());
                         }else {
                             log.error("AB车临停转车位时间同步车场失败：{}", info.getCarNo());
                         }
                     }
                 }
             }else {//非月卡车出场
                //查询车场中已经存在的车辆是否为月卡车
                List<CarInfo> monthCarNos = carInfoService.getMonthCarNo(carInfo.getTenantId(),carInfo.getParkId(), recordCarNoIds);
                if (monthCarNos == null || monthCarNos.size() == 0){
                    //将当前出厂车辆设置为月卡
                    List<CarInfo> carMonthlyRent = carInfoService.findByIds(Arrays.asList(carInfo.getId()));
                    log.info("临停出场，车场中无月卡车 ，修改出场车辆为月卡：{},开始：{}结束时间：{}", carMonthlyRent.get(0),DateUtils.date2Str(carPort.getLocalStartTime(),DateUtils.datetimeFormat),DateUtils.date2Str(carPort.getLocalEndTime(),DateUtils.datetimeFormat));
                    ForeignCarMonthlyRentReq rentReq = new ForeignCarMonthlyRentReq();
                    rentReq.setPark_id(carMonthlyRent.get(0).getOutParkId());
                    if (StringUtils.isNotBlank(carMonthlyRent.get(0).getOwnerName())){
                        rentReq.setEmp_name(carMonthlyRent.get(0).getOwnerName());
                    } else {
                        rentReq.setEmp_name(carMonthlyRent.get(0).getMobile());
                    }
                    rentReq.setEmp_moblie(carMonthlyRent.get(0).getMobile());
                    rentReq.setPlate_number(carMonthlyRent.get(0).getCarNo());
                    rentReq.setCartypeid(carMonthlyRent.get(0).getOutCarType());
                    rentReq.setCarmodelid(carMonthlyRent.get(0).getOutCarModel());
                    rentReq.setBegindate(DateUtils.date2Str(carPort.getLocalStartTime(),DateUtils.datetimeFormat));
                    rentReq.setEnddate(DateUtils.date2Str(carPort.getLocalEndTime(),DateUtils.datetimeFormat));
                    Result<String> syncRes = saveMonthlyRent(rentReq);
                    if (syncRes.isSuccess()){
                        log.info("AB车临停转车位时间同步车场成功：{}", carMonthlyRent.get(0).getCarNo());
                        carMonthlyRent.get(0).setLocalStartTime(carPort.getLocalStartTime());
                        carMonthlyRent.get(0).setLocalEndTime(carPort.getLocalEndTime());
                        carInfoService.updateFeeDate(carMonthlyRent.get(0));
                    }else{
                        log.info("AB车临停转车位时间同步车场失败：{}", carMonthlyRent.get(0).getCarNo());
                    }
                }
             }
        }else {//车场中无车辆
            List<CarInfo> carMonthlyRent = carInfoService.findByIds(carInfoList.stream().map(CarInfo::getId).collect(Collectors.toList()));
            for (CarInfo info : carMonthlyRent) {
                //车辆未审核通过 || 未同步车场 不做处理
                if (!(IParkConstants.CHECK_STATUS_PASSED == info.getCheckStatus()) || info.getSyncStatus().equals(CarSyncStatusEnum.SYNC_STATUS_NO.getCode())) {
                    continue;
                }
                log.info("车辆出场，车场中无车辆修改车辆为月卡：{},开始时间：{}，结束时间：{}",carInfo.getCarNo(),DateUtils.date2Str(carPort.getLocalStartTime(),DateUtils.datetimeFormat),DateUtils.date2Str(carPort.getLocalEndTime(),DateUtils.datetimeFormat));
                ForeignCarMonthlyRentReq rentReq = new ForeignCarMonthlyRentReq();
                rentReq.setPark_id(info.getOutParkId());
                if (StringUtils.isNotBlank(info.getOwnerName())){
                    rentReq.setEmp_name(info.getOwnerName());
                } else {
                    rentReq.setEmp_name(info.getMobile());
                }
                rentReq.setEmp_moblie(info.getMobile());
                rentReq.setPlate_number(info.getCarNo());
                rentReq.setCartypeid(info.getOutCarType());
                rentReq.setCarmodelid(info.getOutCarModel());
                //将剩余第一个进入车场的车辆时间设置为车位时间
                rentReq.setBegindate(DateUtils.date2Str(carPort.getLocalStartTime(),DateUtils.datetimeFormat));
                rentReq.setEnddate(DateUtils.date2Str(carPort.getLocalEndTime(),DateUtils.datetimeFormat));
                Result<String> syncRes = saveMonthlyRent(rentReq);
                if (syncRes.isSuccess()){
                    info.setLocalStartTime(carPort.getLocalStartTime());
                    info.setLocalEndTime(carPort.getLocalEndTime());
                    carInfoService.updateFeeDate(info);
                    log.info("AB车临停转车位时间同步车场成功：{}", info.getCarNo());
                }else {
                    log.error("AB车临停转车位时间同步车场失败：{}", info.getCarNo());
                }
            }
        }
    }

    private String createSign(Map<String,Object> paramMap){
        if (paramMap == null || paramMap.size() <= 0 ) return null;
        StringBuilder sb = null;
        for (Map.Entry<String,Object> param : paramMap.entrySet()){
            if (param.getValue() == null) continue;
            if (sb == null){
                sb = new StringBuilder();
            } else {
                sb.append("&");
            }
            sb.append(param.getKey()).append("=").append(param.getValue());
        }
        return sb.toString();
    }

}
